package vip.zhenzicheng.nettyadv.client;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.ReadTimeoutException;
import io.netty.util.ReferenceCountUtil;
import vip.zhenzicheng.nettyadv.constant.MessageType;
import vip.zhenzicheng.nettyadv.server.HeartBeatRespHandler;
import vip.zhenzicheng.nettyadv.vo.MsgHeader;
import vip.zhenzicheng.nettyadv.vo.MyMessage;

import java.util.logging.Logger;

/**
 * 客户端在一段时间未向服务器发送业务请求时，发出心跳请求报文
 *
 * @author zhenzicheng
 * @date 2022-06-14 10:21
 */
public class HeartBeatReqHandler extends ChannelInboundHandlerAdapter {

  private static final Logger LOG = Logger.getLogger(HeartBeatRespHandler.class.getSimpleName());

  @Override
  public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt == IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT) {
      MyMessage heartBeat = buildHeatBeat();
      LOG.info("写空闲，发出心跳报文维持连接： " + heartBeat);
      ctx.writeAndFlush(heartBeat);
    }
    super.userEventTriggered(ctx, evt);
  }

  private MyMessage buildHeatBeat() {
    MyMessage message = new MyMessage();
    MsgHeader msgHeader = new MsgHeader();
    msgHeader.setType(MessageType.HEARTBEAT_REQ.value());
    message.setMsgHeader(msgHeader);
    return message;
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    MyMessage message = (MyMessage) msg;
    /*是不是心跳的应答*/
    if (message.getMsgHeader() != null && message.getMsgHeader().getType() == MessageType.HEARTBEAT_RESP.value()) {
      LOG.info("收到服务器心跳应答，服务器正常");
      ReferenceCountUtil.release(msg);
    } else {
      ctx.fireChannelRead(msg);
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    if (cause instanceof ReadTimeoutException) {
      LOG.warning("服务器长时间未应答，关闭链路");
      //ctx.close();
    }
    super.exceptionCaught(ctx, cause);
  }
}
